/*
 *	uart.c   -  uart api & driver 
 *	
 *	Author: 	li ming <admin@lumit.org>
 *	Date:		2008-4-16
 *	Copyleft:	http://www.lumit.org
 */
 
#include "uart.h"

/* define the relative gpio register */
#define SYSCFG      0x03FF0000
#define UART0_BASE	(SYSCFG + 0xD000)
#define UART1_BASE 	(SYSCFG + 0xE000)

#define UART0_ULCON		(*((volatile unsigned *)(UART0_BASE+0x00)))
#define UART0_UCON		(*((volatile unsigned *)(UART0_BASE+0x04)))

/* Line control register bits */
#define	ULCON	0x00
#define	UCON	0x04
#define	USTAT	0x08
#define	UTXBUF	0x0C
#define	URXBUF	0x10
#define	UBRDIV	0x14

/* UART Control Register bits */
#define	ULCR8bits	(3)
#define	ULCRS1StopBit	(0)
#define	ULCRNoParity	(0)

/* UART Status Register bits */
#define USROverrun     	(1 << 0)
#define	USRParity      	(1 << 1)
#define	USRFraming     	(1 << 2)
#define	USRBreak       	(1 << 3)
#define	USRDTR		(1 << 4)
#define	USRRxData      	(1 << 5) 
#define	USRTxHoldEmpty 	(1 << 6)
#define	USRTxEmpty     	(1 << 7)

/* default baud rate value */
#define BAUD_9600	(162 << 4)
#define BAUD_19200	(80 << 4)
#define BAUD_38400	(40 << 4)
#define BAUD_57600	(26 << 4)
#define BAUD_115200	(13 << 4)

/* UART primitives */
#define GET_STATUS(p)	(*(volatile unsigned  *)((p) + USTAT))
#define RX_DATA(s)     	((s) & USRRxData)
#define GET_CHAR(p)	(*(volatile unsigned  *)((p) + URXBUF))
#define TX_READY(s)    	((s) & USRTxHoldEmpty)
#define PUT_CHAR(p,c)  	(*(unsigned  *)((p) + UTXBUF) = (unsigned )(c))

/* ************************************************************************ */
int uart0_init(void)
{
    /* Set port for 8 bit, one stop, no parity  */
	*(volatile unsigned *)(UART0_BASE + ULCON) = ULCR8bits;
	 
	*(volatile unsigned *)(UART0_BASE + UBRDIV) = BAUD_19200;
	
	return 0;
}
 
int uart0_putchar(char ch)
{		
	/* read tx ready flag, when =1 break */
	while ( TX_READY(GET_STATUS(UART0_BASE))==0)
		;
	PUT_CHAR(UART0_BASE, ch);
	return 0;
}

char uart0_getchar(void)
{
	char ch;
 
	while ( (RX_DATA(GET_STATUS(UART0_BASE)))==0 )
		;		
	
	ch = GET_CHAR(UART0_BASE);
	return ch;
}

int uart0_test(void)
{
	char ch;
	
	uart0_init();
	
	while(1)
	{
		ch = uart0_getchar();
		uart0_putchar(ch);
	}	
}